#include "game.h"


game::game()
{
  m_running = false;
  m_paused = false;
  m_direction = true;
  m_difficulty = 1;
  m_scoreA = 0;
  m_scoreB = 0;
  m_sScore = (char*)malloc(sizeof(char)*256);
  m_paddleSpeed = 5;
  
  setBallDirection("west");

  posPaddleA[0] = 80; // x
  posPaddleA[1] = 160; // y

  posPaddleB[0] = 400;
  posPaddleB[1] = 160;

  posBall[0] = 240;
  posBall[1] = 160;
  
  posNetA[0] = 0;
  posNetA[1] = 0;
  
  posNetB[0] = 410;
  posNetB[1] = 0;
  
  posNetC[0] = 0;
  posNetC[1] = 20;
  
  posNetD[0] = 0;
  posNetD[1] = 300;
}

void game::setBallDirection(char *direction)
{
  // clear out existing settings
  for(int i=0; i<(sizeof(m_directionArray)/sizeof(int)); i++)
  {
	m_directionArray[i] = 0;
  }
  // mark the end (for filtering purposes, later)
  m_directionArray[9] = 666;
/*

	Direction works like so:
	0 1 2
	3 4 5
	6 7 8
	
	4 is not used, and is always 0. If 0 is 1, direction is northwest.
	I think you get the idea.

*/
  if(!(strcmp(direction, "west"))) // ball needs to be travelling west
    m_directionArray[3] = 1;
  else if(!(strcmp(direction, "east")))
    m_directionArray[5] = 1;
  else if(!(strcmp(direction, "north")))
    m_directionArray[1] = 1;
  else if(!(strcmp(direction, "south")))
    m_directionArray[7] = 1;
  else if(!(strcmp(direction, "northwest")))
    m_directionArray[0] = 1;
  else if(!(strcmp(direction, "southwest")))
    m_directionArray[6] = 1;
  else if(!(strcmp(direction, "northeast")))
    m_directionArray[2] = 1;
  else if(!(strcmp(direction, "southeast")))
    m_directionArray[8] = 1;
}

char *game::getBallDirection()
{
	int *i, j = 0;
	i = &m_directionArray[0];
	for(; *i++ != 666; ++j)
	  if(*i == 1)
	    break;
	j++; // dunno why it's needed :(
	switch(j)
	{
	  case 0:
	    return "northwest";
	    break;
	  case 1:
	    return "north";
	    break;
	  case 2:
	    return "northeast";
	    break;
	  case 3:
	    return "west";
	    break;
	  case 4:
	    return "error 1";
	    break;
	  case 5:
	    return "east";
	    break;
	  case 6:
	    return "southwest";
	    break;
	  case 7:
	    return "south";
	    break;
	  case 8:
	    return "southeast";
	    break;
    }
    
    return "error 2";
}

bool game::running()
{
  return m_running;
}

void game::resetBallPosition()
{
  posBall[0] = 240;
  posBall[1] = 160;
}

int game::getBallSpeed()
{
  return m_difficulty;
}

int game::getPaddleSpeed()
{
  return m_paddleSpeed;
}

int game::setBallSpeed(int i)
{
  m_difficulty = i;
  return m_difficulty;
}

int game::setPaddleSpeed(int i)
{
  m_paddleSpeed = i;
  return m_paddleSpeed;
}

void game::startSinglePlayerVsAI()
{
  m_running = true;

  while(m_running)
  {
	input::update();

	int last = posPaddleA[1];
	
	if(input::isKeyDown(input::KEY_DOWN))
	  posPaddleA[1]+=getPaddleSpeed();
	else if(input::isKeyDown(input::KEY_UP))
	  posPaddleA[1]-=getPaddleSpeed();
	else if(input::isKeyDown(input::KEY_ESCAPE))
	  m_running = false;

	if(last != posPaddleA[1])
	  printf("%d\n", posPaddleA[1]);

    bboxPaddleA = new bbox(posPaddleA[0], posPaddleA[1], posPaddleA[0]+14, posPaddleA[1]+60);
    bboxPaddleB = new bbox(posPaddleB[0], posPaddleB[1], posPaddleB[0]+14, posPaddleB[1]+60);
    bboxBall = new bbox(posBall[0], posBall[1], posBall[0]+16, posBall[1]+16);
    bboxNetA = new bbox(posNetA[0], posNetA[1], posNetA[0]+70, posNetA[1]+320);
    bboxNetB = new bbox(posNetB[0], posNetB[1], posNetB[0]+480, posNetB[1]+320);
    bboxNetC = new bbox(posNetC[0], posNetC[1], posNetC[0]+20, posNetC[1]+20);
    bboxNetD = new bbox(posNetD[0], posNetD[1], posNetD[0]+20, posNetD[1]+20);
    
    char *d;
    d = (char*)malloc(15);
    strcpy(d, getBallDirection());
    
    bbox collision = bbox::intersection(*bboxPaddleA, *bboxBall);
	if(collision > 0)
	{
	  setBallDirection("northeast");
	  //m_direction = false; // change it so that the ball moves in opposite direction of paddle A
	  //audio::openMusic("bounce"); hello seg fault
	  puts("Impact A!");
	  m_difficulty += m_difficulty;
	  increaseScore('a', 25);
	  //m_scoreA += 25;
    }
    
    collision = bbox::intersection(*bboxPaddleB, *bboxBall);
    if(collision > 0)
    {
	  setBallDirection("southwest");
	  //m_direction = true;
	  puts("Impact B!");
	  m_difficulty += m_difficulty;
	  increaseScore('b', 25);
	  //m_scoreB += 25;
    }
    
    collision = bbox::intersection(*bboxNetA, *bboxBall);
    if(collision > 0)
    {
	  puts("Ball caught in net A.");
	  // deduct points to player A
	  // reset difficulty
	  m_difficulty = 1;
	  resetBallPosition();
	  decreaseScore('a', 25);
	  //m_scoreA -= 25;
    }
    
    collision = bbox::intersection(*bboxNetB, *bboxBall);
    if(collision > 0)
    {
	  puts("Ball caught in net B.");
	  // deduct points to player B
	  // reset difficulty
	  m_difficulty = 1;
	  resetBallPosition();
	  decreaseScore('b', 25);
	  //m_scoreB -= 25;
    }
    
    collision = bbox::intersection(*bboxNetC, *bboxBall);
    if(collision > 0)
    {
	  puts("Ball caught in net C.");
	  // rebound the ball: get direction and reverse
	  if(!(strcmp(d, "northeast")))
	    setBallDirection("southeast");
	  else
	    setBallDirection("southwest");
	  //m_directionDiagonalA = (m_directionDiagonalA) ? false : true ;
    }
    
    collision = bbox::intersection(*bboxNetD, *bboxBall);
    if(collision > 0)
    {
	  puts("Ball caught in net D.");
	  // rebound the ball: get direction and reverse
	  if(!(strcmp(d, "southeast")))
	    setBallDirection("northeast");
	  else
	    setBallDirection("northwest");
	  //m_directionDiagonalA = (m_directionDiagonalA) ? false : true ;
    }
    
    // move ball in the right direction
    updateBallPosition();
    //posBall[0] = (m_direction) ? posBall[0]-m_difficulty : posBall[0]+m_difficulty ;

	// update the score string and print it
	sprintf(m_sScore, "%d         |         %d", m_scoreA, m_scoreB);
	screen::drawText(m_sScore, 240, 0);

	screen::drawSprite("ball", posBall[0], posBall[1]);
	screen::drawSprite("paddle", posPaddleA[0], posPaddleA[1]);
	screen::drawSprite("paddle", posPaddleB[0], posPaddleB[1]);

	screen::update();
	
	delete bboxPaddleA;
	delete bboxPaddleB;
	delete bboxBall;
  }
}

void game::updateBallPosition()
{
  puts(getBallDirection());
  if(!(strcmp(getBallDirection(), "northwest")))
  {
    posBall[0]--; posBall[1]--;
  }
  else if(!(strcmp(getBallDirection(), "west")))
  {
    posBall[0]--;
  }
  else if(!(strcmp(getBallDirection(), "southwest")))
  {
    posBall[0]--; posBall[1]++;
  }
  else if(!(strcmp(getBallDirection(), "northeast")))
  {
    posBall[0]++; posBall[1]--;
  }
  else if(!(strcmp(getBallDirection(), "east")))
  {
    posBall[0]++;
  }
  else if(!(strcmp(getBallDirection(), "southeast")))
  {
    posBall[0]++; posBall[1]++;
  }
}

void game::pause()
{
  m_paused = true;
}

void game::resume()
{
  m_paused = false;
}

void game::quit()
{
  m_running = false;
}

void game::increaseScore(char player, int i)
{
  if(player == 'a' || player == 'A')
    m_scoreA += i;
  else if(player == 'b' || player == 'B')
    m_scoreB += i;
  else return;
}

void game::decreaseScore(char player, int i)
{
  if(player == 'a' || player == 'A')
    m_scoreA -= i;
  else if(player == 'b' || player == 'B')
    m_scoreB -= i;
  else return;
}

